home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 52
/
Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso
/
Aminet
/
misc
/
emu
/
Apex-src.lha
/
COPY.XPL
< prev
next >
Wrap
Text File
|
2001-09-30
|
15KB
|
674 lines
\COPY.XPL JUL-07-88
\COPY UTILITY FOR APEX VERSION 1.8-68K
\REVISION HISTORY:
\NOV-85, Added verify when replacing older file with a newer one, added date,
\ added one disk copy, and rearranged miscellaneous stuff, L.B.
\MAR-12-86, Modified for 32-bit XPL on the Stride, L.B.
\JUN-13-86, Allow lowercase characters, L.B.
\OCT-13-86, Modify for new system page
\DEC-08-86, Changed CONWID (it's no longer on SYSPAG)
\APR-10-87, Changed BLIT and string conventions.
\JUL-07-88, Added protection aginst copying to a non-Apex disk, use FREE
\ intrinsic.
code REM=2, RESERVE=3, SWAP=4, REBEGIN=6,
CHIN=7, CHOUT=8, CRLF=9, INTIN=10,
INTOUT=11, TEXT=12, OPENI=13, FREE=18,
WRITE=30, READ=31, BLIT=36;
\THE DIRECTORY:
addr FNAME, \THE NAME AND EXTENSION FOR EACH FILE
FSTAT, \THE STATUS FOR EACH FILE
STAB, \SORT TABLE, ORDER IN ASCENDING "FBLK"S
NUMVAL, \LAST ELEMENT OF "STAB" ARRAY (MAXSTB)
DIRCHG, \"$A5" INDICATES DIRECTORY NEEDS TO BE SORTED
PRDEV, \DEFAULT DEVICE NUMBER
DFNAME, \THE DEFAULT FILE NAME AND EXTENTION
TITLE, \TITLE OF THE VOLUME
UNUSED, \UNUSED SPACE
APEXID, \A 4-BYTE VALUE USED TO RECOGNIZE AN APEX DISK
FLAGS; \I.E: PACK, BACKUP, CHECK, UNLOCKED, SEARCH, ABORT
\16-BIT INTEGER ARRAYS IN THE DIRECTORY:
int FBLK, \THE FIRST BLOCK OF EACH FILE
LBLK, \THE LAST BLOCK
FEMBLK, \EMPTY BLOCKS FILE LIST (FIRST BLOCK)
LEMBLK, \ (LAST BLOCK) SORTED LARGEST SIZE FIRST
PMAXB, \MAXIMUM BLOCK NUMBER (= UNIT SIZE -1)
VOLUME, \UNIQUE VOLUME (DIRECTORY) ID NUMBER
DIRDAT, \DIRECTORY DATE (SYSTEM DATE)
FDATE; \DATE FOR EACH FILE
\DEFINE SOME OFFSETS INTO SYSTEM PAGE
\THE SYSTEM GLOBALS:
addr PARM, \SYSTEM PAGE PARAMETERS
MOSTR, \ARRAY OF MONTH NAMES (STRING)
LOCNAM; \LOCAL NAME OF FILE
int CONWID, \WIDTH OF CONSOLE (CHARACTERS)
BLKSIZ, \SIZE OF A BLOCK IN BYTES
DIRSIZ, \DIR SIZE
DIRBLK, \WHERE DIRECT IS
USERBLK, \FIRST USER BLOCK
BACKBLK, \BLOCK TO PU BACKUP DIR IN
FIRBLK, \FIRST BLOCK OF FILE
LASBLK, \LAST BLOCK OF FILE
FLNO, \NUMBER OF FILE
MAXBLK, \HIGHEST BLOCK
MAXFL, \HIGHEST FILE NO
CHAR, \INPUT CHARACTER
SYSDAT, \SYSTEM DATE
INDATE, \DATE OF LAST INFILE
MAXSTB; \SIZE OF STAB ARRAY
int DIRLEN; \ARRAY: LENGTHS (IN WORDS) OF SEGMENTS OF THE DIRECTORY
def MAXSEG=10; \THE LAST SEGMENT (ELEMENT) IN "DIRLEN"
def EXTPAT=$A5; \FLAG PATTERN INDICATING EXTENDED DIR IS USED
\FOR MAIN:
int FILE,TOBLK,FRBLK,SIZE,BUFSIZ,RDSIZ,II,L,
DRIVE,FRDRV,TODRV,NEXFL,MAXDRV;
addr BUFFER,MYNAME;
\CONSTANTS:
\FILE STATUS IN THE DIRECTORY:
def NULL=0,TENTATIVE=255,REPLACE=254,VALID=1;
\FAILED FLAG
def NONE=$FFFF;
def SP=$20;
\----------------------------------------------------------------------\
proc PUT16(ARRAY, INDEX, VALUE);
\STORE A 16-BIT VALUE INTO THE DIRECTORY ARRAY ENTRY AT "INDEX"
\NOTE THE BYTE ORDER IS LOW BYTE, HIGH BYTE
addr ARRAY;
int INDEX, VALUE;
begin
INDEX:= INDEX + INDEX; \DOUBLE FOR WORD ENTRIES
ARRAY(INDEX):= VALUE; \STORE LOW BYTE
ARRAY(INDEX+1):= SWAP(VALUE); \STORE HIGH BYTE
end; \PUT16
func GET16(ARRAY, INDEX);
\RETURN A 16-BIT VALUE FROM THE DIRECTORY ARRAY ENTRY AT "INDEX"
\NOTE THE BYTE ORDER IS LOW BYTE, HIGH BYTE
addr ARRAY;
int INDEX;
begin
INDEX:= INDEX + INDEX; \DOUBLE FOR WORD ENTRIES
return ARRAY(INDEX) + SWAP(ARRAY(INDEX+1));
end; \GET16
\----------------------------------------------------------------------\
proc NEXT;
begin
CHAR:= CHIN(0);
if CHAR>=^a & CHAR<=^z then CHAR:=CHAR -32; \CONVERT TO UPPERCASE
end; \NEXT
proc CR;
CRLF(0);
proc TXT(STR);
addr STR;
TEXT(0,STR);
proc NUMOUT(I);
int I;
INTOUT(0,I);
func ALPHANUM; \CHECK FOR ALPHANUMERIC OR "?"
return ((CHAR>=^0)&(CHAR<=^9))!((CHAR>=^A)&(CHAR<=^Z))!(CHAR=^?);
\----------------------------------------------------------------------\
func VERIFY; \RETURN 'TRUE' IF "Y" (OR "y") IS TYPED IN
begin
TXT(" - ARE YOU SURE (N/Y)? ");
OPENI(0);
return (CHIN(0)!$20)= ^y;
end; \VERIFY
proc NEWDISK(FLAG); \PROMPT USER TO INSERT DISK
int FLAG;
begin
if TODRV=FRDRV then
begin
TEXT(0,if FLAG then "INSERT COPY DISK"
else "RESTORE ORIGINAL DISK");
while not VERIFY do;
end;
end; \NEWDISK
proc PRDATE(DATE); \OUTPUT THE DATE, E.G: NOV-07-85
int DATE;
int DAY,MO,I;
proc NUM2(N);
int N;
begin
if N<10 then CHOUT(0,^0);
NUMOUT(N);
end; \NUM2
begin
if DATE<=0 then [TXT("NO DATE "); return];
DATE:= DATE/32;
DAY:= REM(0);
DATE:= DATE/16;
MO:= REM(0);
MO:= (MO-1)*3;
for I:= 0,2 do CHOUT(0,MOSTR(MO+I));
CHOUT(0,^-);
NUM2(DAY);
CHOUT(0,^-);
NUM2(DATE+76);
end; \PRDATE
\----------------------------------------------------------------------\
proc NAME(DEFAULT);
\GET A FILE NAME FROM THE OPERATOR AND PUT IT INTO "LOCNAM".
\ SET TO DEFAULT EXTENSION IF NONE WAS GIVEN. EXPAND *'S INTO FIELDS OF ?'S.
\OUTPUTS: LOCNAM FILE NAME AND EXTENSION
\ LOCDEV DEVICE (UNIT) NUMBER
addr DEFAULT; \DEFAULT EXTENSION
int K;
begin
if CHAR#13\CR\ then NEXT;
while CHAR=SP do NEXT;
K:= 0;
while ALPHANUM do
begin
LOCNAM(K):= CHAR;
if K<8 then K:= K+1;
NEXT;
end;
if CHAR=^* then \FILL OUT THE REST OF THE NAME WITH "?"
[for K:= K,7 do LOCNAM(K):= ^?;
NEXT]
else for K:= K,7 do LOCNAM(K):= SP;
if CHAR=^. then
begin
NEXT;
K:= 8;
while ALPHANUM do
begin
LOCNAM(K):= CHAR;
if K<11 then K:= K+1;
NEXT;
end;
if CHAR=^* then
[for K:= K,10 do LOCNAM(K):= ^?;
NEXT]
else for K:= K,10 do LOCNAM(K):= SP;
end
else begin
LOCNAM(8):= DEFAULT(0);
LOCNAM(9):= DEFAULT(1);
LOCNAM(10):= DEFAULT(2);
end;
end; \NAME
proc ERROR(STR); \YOU BLEW IT BABES!
addr STR;
begin
CR;
CHOUT(0,$07); \BEL
TXT("NOPE - "); TXT(STR); CR;
NEWDISK(false); \RESTORE ORIGINAL DISK
CR;
\PARM(EXECUT):= $FF; \\ABORT ANY COMMAND FILE
\PARM(LINIDX):= $FF;
REBEGIN;
end; \ERROR
\----------------------------------------------------------------------\
proc MOVIT(AB1,AB2,LEN); \MOVE "LEN" WORDS INTO B1 FROM B2
int AB1,AB2,LEN,LEN2; \B1 & B2 ARE LEFT POINTING TO THE LAST POSITION
int B1, B2, I;
begin
B1:= AB1(0);
B2:= AB2(0);
LEN2:= LEN+LEN;
BLIT(B2, B1, LEN2);
AB1(0):= B1 + LEN2;
AB2(0):= B2 + LEN2;
end; \MOVIT
proc GETDIR(DEV, BAKDIR); \READ IN THE DIRECTORY
int DEV, BAKDIR;
int I, EXTDIR, BASE1, BASE2, BASE3;
begin
EXTDIR:= RESERVE(1024);
\READ THE EXTENDED DIR INTO "EXTDIR"
READ(DEV, if BAKDIR then 5 else 1, EXTDIR, DIRSIZ);
\READ PRIMARY DIRECTORY INTO THE BIG DIRECTORY SPACE
READ(DEV, if BAKDIR then 13 else 9, FNAME, DIRSIZ);
\MERGE THE EXTENDED DIRECTORY INTO THE PRIMARY DIRECTORY
BASE1:= FNAME+528; \(FSTAT)
BASE2:= EXTDIR+528;
BASE3:= FSTAT;
for I:= 0,MAXSEG do
begin
MOVIT(addr BASE3, addr BASE1, DIRLEN(I));
MOVIT(addr BASE3, addr BASE2, DIRLEN(I));
end;
BLIT(EXTDIR, FNAME+528, 528);
MAXFL:= if FLAGS(7)=EXTPAT then 95 else 47;
end; \GETDIR
proc PUTDIR(DEV, BAKDIR); \WRITE THE DIRECTORY
int DEV, BAKDIR;
int I, EXTDIR, BASE1, BASE2, BASE3;
begin
EXTDIR:= RESERVE(1024);
\SEPARATE THE BIG DIR INTO THE PRIMARY DIR AND THE EXTENDED DIR
BLIT(FNAME+528, EXTDIR, 528);
BASE1:= FNAME+528;
BASE2:= EXTDIR+528;
BASE3:= FSTAT;
for I:= 0,MAXSEG do
begin
MOVIT(addr BASE1, addr BASE3, DIRLEN(I));
MOVIT(addr BASE2, addr BASE3, DIRLEN(I));
end;
\IF EXTENDED DIR IS USED THEN WRITE "EXTDIR" INTO THE EXTENDED DIR
if FLAGS(7)=EXTPAT then
WRITE(DEV, if BAKDIR then 5 else 1, EXTDIR, DIRSIZ);
\WRITE THE PRIMARY DIR
WRITE(DEV, if BAKDIR then 13 else 9, FNAME, DIRSIZ);
\NOW FIX THE BIG DIR
BLIT(EXTDIR, FNAME+528, 528);
end; \PUTDIR
proc WRTDIR;
int BITS;
begin
BITS:= [$01,$02,$04,$08,$10,$20,$40,$80];
\PARM(UNTUPD):= PARM(UNTUPD)!BITS(DRIVE);
DIRCHG(0):= $A5;
APEXID(0):= ^a;
APEXID(1):= ^p;
APEXID(2):= ^e;
APEXID(3):= ^x;
PUTDIR(DRIVE,false);
end; \WRTDIR
\----------------------------------------------------------------------\
func LOOKUP(FILE);
\LOOKUP THE FILENAME IN LOCFILE BEGINNING AT DIRECTORY ENTRY NUMBER "FILE".
\TAKE "?" AS WILD. RETURN THE FILE NUMBER.
int FILE;
int L;
begin
loop begin
if FSTAT(FILE)=VALID then
begin
L:= 0;
loop begin
if (LOCNAM(L)#^?) & (FNAME(FILE*11+L)#LOCNAM(L))
then quit;
L:= L+1;
if L=11 then quit;
end;
if L=11 then quit; \WE HAVE IT
end;
FILE:= FILE+1;
if FILE>MAXFL then quit;
end;
return if FILE<=MAXFL then FILE else NONE;
end; \LOOKUP
proc PRINT(FILE);
int FILE,MIN,MAX,K,SIZE;
begin
NUMOUT(DRIVE);
CHOUT(0,^:);
for K:= 0,7 do CHOUT(0,FNAME(FILE*11+K));
CHOUT(0,^.);
for K:= 8,10 do CHOUT(0,FNAME(FILE*11+K));
MIN:= GET16(FBLK,FILE);
MAX:= GET16(LBLK,FILE);
SIZE:= MAX-MIN+1;
TXT(" "); NUMOUT(SIZE);
if SIZE<10 then CHOUT(0,SP);
if SIZE<100 then CHOUT(0,SP);
if SIZE<1000 then CHOUT(0,SP);
TXT(" ");
if CONWID>60 then [PRDATE(GET16(FDATE,FILE)); TXT(" ")];
NUMOUT(MIN); CHOUT(0,^-); NUMOUT(MAX);
end; \PRINT
\----------------------------------------------------------------------\
proc RDDIR;
begin
GETDIR(DRIVE,false);
MAXBLK:= GET16(PMAXB,0);
end; \RDDIR
proc GETNAM(FILE);
int FILE,I;
for I:= 0,10 do LOCNAM(I):= FNAME(FILE*11+I);
func EMSIZ(I);
int I;
begin
FIRBLK:= if I<0 then USERBLK else GET16(LBLK,STAB(I)) +1;
LASBLK:= if (MAXSTB<0)!(MAXSTB=I) then MAXBLK
else GET16(FBLK, STAB(I+1)) - 1;
return if LASBLK>=FIRBLK then LASBLK-FIRBLK+1 else 0;
end; \EMSIZ
\----------------------------------------------------------------------\
proc SORT; \BUBBLE SORT THE FILES INTO ASCENDING FBLK
int I,J,T;
begin
J:= 0;
for I:= 0,MAXFL do
if FSTAT(I)=VALID then
[STAB(J):= I; J:= J+1];
MAXSTB:= J-1;
for I:= 0,MAXSTB-1 do
if GET16(FBLK, STAB(I+1)) < GET16(FBLK, STAB(I)) then
\WE ARE OUT OF ORDER SO...
begin
J:= I;
repeat begin
T:= STAB(J);
STAB(J):= STAB(J+1);
STAB(J+1):= T;
J:= J-1;
end
until GET16(FBLK, STAB(J)) < GET16(FBLK, STAB(J+1)) ! J<0;
end;
end; \SORT
proc FIND(SIZE); \FIND FIXED SIZE SPACE, SET FIRST AND LAST BLOCK TO IT
int SIZE,I;
begin
if SIZE<=0 then ERROR("BAD FILE");
SORT;
I:= -1;
while EMSIZ(I)<SIZE & I<=MAXSTB do I:= I+1;
if I>MAXSTB then ERROR("NOT ENOUGH SPACE");
LASBLK:= FIRBLK+SIZE-1;
end; \FIND
\----------------------------------------------------------------------\
proc ENTER; \ENTER A TENTATIVE FILE AND ITS BLOCKS INTO THE DIRECTORY
int K; \DON'T RESERVE THE BLOCKS, DON'T MARK IT VALID
begin
for K:= 0,10 do
if LOCNAM(K)=^? then ERROR("BAD FILE");
\FIND AN EMPTY DIR SLOT
FLNO:= 0;
while FSTAT(FLNO)=VALID do
begin
FLNO:= FLNO+1;
if FLNO>MAXFL then ERROR("DIRECTORY IS FULL");
end;
\NOW COPY THE NAME INTO IT
for K:= 0,10 do FNAME(FLNO*11+K):= LOCNAM(K);
PUT16(FBLK, FLNO, FIRBLK);
PUT16(LBLK,FLNO,LASBLK);
FSTAT(FLNO):= REPLACE;
PUT16(FDATE,FLNO,INDATE);
end; \ENTER
proc CLOMARK(FILE);
int FILE;
begin
FSTAT(FILE):= VALID;
FIRBLK:= GET16(FBLK,FILE);
LASBLK:= GET16(LBLK,FILE);
TXT("CLOSING: "); PRINT(FILE);
CR;
end; \CLOMARK
\----------------------------------------------------------------------\
proc CLOFIL(FILE);
int FILE,S,FILENO;
proc CLEAR(FILE);
int FILE;
begin
\REMOVE A ENTRY FROM THE DIRECTORY, FREE UP ITS BLOCKS
if FSTAT(FILE)#VALID then return;
FSTAT(FILE):= NULL;
TXT("REMOVING: "); PRINT(FILE);
CR;
end; \CLEAR
begin \CLOFIL
\CLOSE THE TENTATIVE FILE BY DIRECTORY NUMBER
\ASSUME IT HAS BEEN ENTERED
\REMOVE COLLISIONS
S:= FSTAT(FILE);
if (S#TENTATIVE)&(S#REPLACE) then ERROR("INTERNAL ERROR");
GETNAM(FILE);
\REMOVE ANY COLLISIONS WITH LOCFILE
\NEW FILE = "FILE" (OR LOCFILE OR FLNO), EXISTING FILE = "FILENO"
FILENO:= LOOKUP(0);
if FILENO=NONE then CLOMARK(FILE)
else begin
if INDATE<GET16(FDATE,FILENO) then
begin
TXT("ABOUT TO REPLACE NEWER FILE");
if VERIFY then
begin
CLEAR(FILENO); \GO AHEAD AND DO IT
CLOMARK(FILE);
end
else FSTAT(FILE):= NULL; \REMOVE TENATIVE FILE
end
else begin
CLEAR(FILENO);
CLOMARK(FILE);
end;
end;
end; \CLOFIL
\----------------------------------------------------------------------\
proc READBUF;
begin
RDSIZ:= if SIZE>BUFSIZ then BUFSIZ else SIZE;
READ(DRIVE,FRBLK,BUFFER,RDSIZ);
end; \READBUF
proc WRTBUF;
begin
WRITE(DRIVE,TOBLK,BUFFER,RDSIZ);
FRBLK:= FRBLK+RDSIZ;
TOBLK:= TOBLK+RDSIZ;
SIZE:= SIZE-RDSIZ;
end; \WRTBUF
\----------------------------------------------------------------------\
begin \MAIN
MOSTR:= "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
DIRLEN:= [24, 48, 48, 6, 6, 24, 8, 16, 16, 48, 4];
PARM:= $0400; \LOCATION OF RESIDENT SYSTEM PAGE
CONWID:= 80; \GET CONSOLE WIDTH
BLKSIZ:= 256; \SIZE OF A BLOCK IN BYTES
DIRBLK:= 9; \LOCATION OF DIRECTORY BLOCK
DIRSIZ:= 4; \SIZE OF DIRECTORY IN "BLKSIZ" BLOCKS
BACKBLK:= DIRBLK + DIRSIZ; \LOCATION OF BACKUP DIRECTORY
USERBLK:= BACKBLK + DIRSIZ; \START OF USER FILE SPACE
MAXFL:= 95; \SELECT SO THAT DIRSIZ IS RIGHT
\RESERVE THE ARRAYS
II:= (MAXFL+1)*2;
\BLOCKS 0-2
FNAME:= RESERVE(8*BLKSIZ); \%%%
FSTAT:= FNAME + ((MAXFL+1)*11);
FBLK:= FSTAT + (MAXFL+1);
LBLK:= FBLK + (II);
\BLOCK 3
FEMBLK:= LBLK + (II);
LEMBLK:= FEMBLK + (24);
STAB:= LEMBLK + (24);
NUMVAL:= STAB + (MAXFL+1);
DIRCHG:= NUMVAL + (1);
PRDEV:= DIRCHG + (1);
PMAXB:= PRDEV + (1);
DFNAME:= PMAXB + (2);
UNUSED:= DFNAME + (11);
TITLE:= UNUSED + (16);
UNUSED:= TITLE + (64);
APEXID:= UNUSED + (24);
VOLUME:= APEXID + (4);
DIRDAT:= VOLUME + (2);
UNUSED:= DIRDAT + (2);
FDATE:= UNUSED + (32);
FLAGS:= FDATE + (II);
\FLAGS + (16);
\NON DIR ARRAYS
LOCNAM:= RESERVE(11);
MYNAME:= RESERVE(11);
MAXDRV:= 7;
TXT("-- COPY, V1.8x5 --
");
BUFSIZ:= FREE/256 -5;
BUFFER:= RESERVE(BUFSIZ*256);
loop begin
NEXFL:= 0;
TXT("FILE? ");
CHAR:= 0;
NAME("@@@");
if LOCNAM(0)=SP then quit;
for II:= 0,10 do MYNAME(II):= LOCNAM(II);
TXT("FROM, TO UNITS? ");
\OPENI(0);
FRDRV:= INTIN(0);
TODRV:= INTIN(0);
CR;
if FRDRV<0 ! FRDRV>MAXDRV ! TODRV<0 ! TODRV>MAXDRV then
ERROR("BAD UNIT NUMBER");
loop begin \OVER ALL FILES THAT MATCH
DRIVE:= FRDRV;
RDDIR;
for II:= 0,10 do LOCNAM(II):= MYNAME(II);
FILE:= LOOKUP(NEXFL);
if FILE=NONE then
begin
if NEXFL=0 then ERROR("NO SUCH FILE");
quit;
end;
NEXFL:= FILE+1;
for II:= 0,10 do LOCNAM(II):= FNAME(FILE*11+II);
TXT("MOVING: "); PRINT(FILE); CR;
FRBLK:= GET16(FBLK,FILE); \ITS FIRST BLOCK
SIZE:= GET16(LBLK,FILE) - FRBLK + 1; \ITS SIZE
INDATE:= GET16(FDATE,FILE); \ITS DATE
READBUF;
NEWDISK(true); \INSERT COPY DISK IF NEEDED
DRIVE:= TODRV;
RDDIR;
if APEXID(0)#^a ! APEXID(1)#^p ! APEXID(2)#^e ! APEXID(3)#^x then
begin
ERROR("NOT AN APEX DIRECTORY");
quit; \DON'T COPY ONTO A NON-APEX DISK OR
end; \ ONTO AN INCORRECTLY SUBBED DISK
FIND(SIZE);
ENTER;
TOBLK:= FIRBLK;
WRTBUF;
while SIZE>0 do
begin
NEWDISK(false); \RESTORE DISK IF NECESSARY
DRIVE:= FRDRV;
READBUF;
NEWDISK(true); \INSERT COPY DISK IF NEEDED
DRIVE:= TODRV;
WRTBUF;
end;
CLOFIL(FLNO);
WRTDIR;
NEWDISK(false); \RESTORE DISK IF NECESSARY
CR;
end;
OPENI(0);
end;
end; \MAIN
d;
CLOFIL(FLNO);
WRTDIR;
NEWDISK(false); \RESTORE DISK IF NECESSARY
CR;
end;
OPENI(0);
end;